package logger

import (
	"bufio"
	"bytes"
	"fmt"
	"github.com/ghostspider/prop"
	"github.com/ghostspider/utils"
	"log"
	"os"
	"path/filepath"
	"strconv"
)

const (
	INFO  = "log.info"
	WARN  = "log.warn"
	DEBUG = "log.debug"
	ERROR = "log.error"
	TRACE = "log.trace"
)

type config struct {
	info  bool
	warn  bool
	error bool
	debug bool
	trace bool
}

var con config

func setConfig() {
	con.info = parseBool(INFO)
	con.warn = parseBool(WARN)
	con.error = parseBool(ERROR)
	con.debug = parseBool(DEBUG)
	con.trace = parseBool(TRACE)

}

func Info(msg string) {
	if con.info {
		file := writerMap[INFO]
		out("INFO ", msg, file)
	}

}

func Debug(msg string) {
	if con.debug {
		file := writerMap[DEBUG]
		out("DEBUG ", msg, file)
	}

}
func Warn(msg string) {
	if con.warn {
		file := writerMap[WARN]
		out("WARN ", msg, file)
	}

}
func Error(msg string) {
	if con.error {
		file := writerMap[ERROR]
		out("ERROR ", msg, file)
	}

}
func Trace(msg string) {
	if con.info {
		file := writerMap[TRACE]
		out("TRACE ", msg, file)
	}

}

func out(level, msg string, file *os.File) {
	var buf bytes.Buffer
	logger := log.New(&buf, level, log.Ldate|log.Ltime|log.Lmicroseconds|log.Llongfile)
	logger.Output(3, msg)
	writer := bufio.NewWriter(file)
	logger.SetOutput(writer)
	logger.Println(msg)
	writer.Flush()
	fmt.Print(&buf)
}

func createLogFile(level string) *os.File {
	root := utils.GetRoot()
	file, _ := os.OpenFile(filepath.Join(root, "logs", level+".log"), os.O_APPEND|os.O_CREATE|os.O_RDWR|os.O_SYNC, 0666)
	return file
}

func Close() {
	if _, ok := writerMap[INFO]; !ok && con.info {
		writerMap[INFO].Close()
	}
	if _, ok := writerMap[WARN]; !ok && con.warn {
		writerMap[WARN].Close()
	}
	if _, ok := writerMap[ERROR]; !ok && con.error {
		writerMap[ERROR].Close()
	}
	if _, ok := writerMap[DEBUG]; !ok && con.debug {
		writerMap[DEBUG].Close()
	}
	if _, ok := writerMap[TRACE]; !ok && con.trace {
		writerMap[TRACE].Close()
	}
}

var writerMap map[string]*os.File

func SetWriterMap() {
	setConfig()
	writerMap = make(map[string]*os.File)

	if _, ok := writerMap[INFO]; !ok && con.info {
		writerMap[INFO] = createLogFile("info")
	}
	if _, ok := writerMap[WARN]; !ok && con.warn {
		writerMap[WARN] = createLogFile("warn")
	}
	if _, ok := writerMap[ERROR]; !ok && con.error {
		writerMap[ERROR] = createLogFile("error")
	}
	if _, ok := writerMap[DEBUG]; !ok && con.debug {
		writerMap[DEBUG] = createLogFile("debug")
	}
	if _, ok := writerMap[TRACE]; !ok && con.trace {
		writerMap[TRACE] = createLogFile("trace")
	}
}

func parseBool(key string) bool {
	bol, err := strconv.ParseBool(prop.GetProp(key))
	if err != nil {
		bol = true
	}
	return bol
}
